<template>
	<view>
		<Navbar :showLeft="false">
			<view class="timer">
				<view>
					<TimerCountUp ref="timerCountUpRef" v-if="examInfo.status == 0" :totalSeconds="examInfo.counter"
						@submit="submit"></TimerCountUp>
					<uni-notice-bar v-else single="true" color="#fff" showIcon style="margin-top: 10px;font-size: 16px;"
						background-color="linear-gradient(to right, #9060df, #6356de)"
						:text="`你的得分:${examInfo.score}分`" />
				</view>
			</view>
		</Navbar>

		<view class="question-list">
			<swiper :current="currentIndex" class="swiper" @change="questionChange"
				:style="{ height: pageHeight + 'px' }">
				<swiper-item v-for="(item, index) in formData.questionList">
					<ExamQuestionItem 
						:cache="cache(item.questionId)" 
						@changeAnswer="changeAnswer"
						@autoSave="(qid, ans) => sendAutoSave(qid, ans)" 
						:showAnswer="examInfo.status == 1" 
						:showUserAnswer="examInfo.status == 1"
						 :data="item"
						 :userAnswer="userAnswerF(item)"
						:index="index"
						 v-model="formData.questionList[index].userAnswer"
						:showHtml="index == currentIndex" 
						:height="pageHeight">
					</ExamQuestionItem>
				</swiper-item>
			</swiper>
		</view>
		<Footer :objectId="currentExamQuestion.questionId + ''" :haveCollect="currentExamQuestion.haveCollect"
			:collectType="2" @updateCollect="updateCollectHandler">
			<view class="footer">
				<view class="btn-panel">
					<view ref="submitButtonRef" class="btn" @click="submit" v-if="examInfo.status == 0">交卷</view>
					<view class="btn" @click="back" v-else>返回</view>
				</view>
				<view class="iconfont icon-more" @click="showQuestionList">
					{{ currentIndex + 1 }}/{{ formData.questionList.length}}
				</view>
			</view>
		</Footer>
		<!--开始考试-->
		<Dialog v-if="examInfo.status == 0" title="确认" ref="startExamRef" :showCancel="false" :okFun="startExam"
			okText="开始答题">
		</Dialog>
		<!--选择题目-->
		<Popup ref="questionPopupRef">
			<view class="pop-question-list">
				<view class="question-item" :style="{
            width: popItemWidth + 'px',
            height: popItemWidth + 'px',
          }" v-for="(item, index) in formData.questionList">
					<view :class="[
              'item-inner',
              (currentIndex == index) ? 'active' : '',
              item.userAnswer ? 'answered' : '',
            ]" :style="{
              width: popItemWidth - 20 + 'px',
              height: popItemWidth - 20 + 'px',
              'border-radius': (popItemWidth - 20) / 2 + 'px',
            }" @click="selectQuestion(index)">{{ index + 1 }}</view>
				</view>
			</view>
		</Popup>
	</view>
</template>

<script setup>
	import TimerCountUp from "@/pages/components/common/TimerCountUp.vue";
	import ExamQuestionItem from "./ExamQuestionItem.vue";
	import {
		LETTER,
		QUESTION_TYPE,
		LOCAL_STORAGE_KEY
	} from "@/utils/Constants.js";
	import {
		useAppInfoStore
	} from "@/stores/appInfo";
	import {
		onLoad,
		onUnload,
	} from "@dcloudio/uni-app";
	import {
		ref,
		reactive,
		getCurrentInstance,
		nextTick,
		computed,
		onMounted,
		onUnmounted
	} from "vue";
	const {
		proxy
	} = getCurrentInstance();
	const appInfoStore = useAppInfoStore();
	const changeAnswer = (obj) => {
		formData.value.answerList.set(obj.questionId, obj)
	}
	//考卷信息
	const submitButtonRef = ref({})
	const startExamRef = ref();
	const examId = ref();
	const startTimer = ref(false)
	const cache = computed(() => (id) => {
		if (examInfo.status == 0) return
		const data = uni.getStorageSync("answerCache")
		return data[id]
	})
	const userAnswerF = computed(() => (item) => {
		const arr = []
		if (item.userAnswer) return item.userAnswer.split(',')
		return arr
	})
	// 添加 WebSocket 服务
	const ws = ref(null); // WebSocket 实例
	const debounceTimer = ref(null) // 防抖计时器
	
	// 初始化 WebSocket 连接
	const initWebSocket = () => {
	  const token = uni.getStorageSync(LOCAL_STORAGE_KEY.token.key);
	  if (!token) return;
	
	  ws.value = new WebSocket(`wss://127.0.0.1:9090/ws/exam?token=${token}`);
	
	  ws.value.onopen = () => {
	    console.log("WebSocket 连接成功");
	  };
	
	  ws.value.onmessage = (event) => {
	    const data = JSON.parse(event.data);
	    if (data.type === "AUTO_SAVE_ACK") {
	      console.log("自动保存确认:", data.payload);
	    }
	  };
	
	  ws.value.onerror = (error) => {
	    console.error("WebSocket 错误:", error);
	  };
	
	  ws.value.onclose = () => {
	    console.log("WebSocket 连接关闭");
	  };
	};
	// 防抖发送答案（500ms间隔）
	const sendAutoSave = (questionId, answer) => {
	  if (debounceTimer.value) clearTimeout(debounceTimer.value);
	  debounceTimer.value = setTimeout(() => {
	    if (ws.value?.readyState === WebSocket.OPEN) {
	      const message = {
	        type: "AUTO_SAVE",
	        payload: {
	          examId: examId.value,
	          questionId,
	          answer: Array.isArray(answer) ? answer.join(",") : answer
	        }
	      };
	      ws.value.send(JSON.stringify(message));
	    }
	  }, 500);
	};
	onMounted(() => {
		initWebSocket()
	})
	onUnmounted(() => {
		if (ws.value) {
		    ws.value.close();
		}
	})
	onLoad((options) => {
		formData.value.questionList = uni.getStorageSync("examQuestionList")
		examInfo.value = uni.getStorageSync("examInfo")
		examId.value = options.examId;
		nextTick(() => {
			currentExamQuestion.value = formData.value.questionList[0]
			if (startExamRef.value) startExamRef.value.show();
		})
	});
	onUnload(() => {
		uni.removeStorageSync("examQuestionList")
		uni.removeStorageSync("examInfo")
		uni.removeStorageSync("answerCache")
	})
	const examInfo = ref({});
	//计算swiper高度
	const pageHeight = computed(() => {
		const {
			statusBar,
			navBarHeight,
			screenHeight
		} = appInfoStore.getInfo();
		return screenHeight - statusBar - navBarHeight - 50;
	});
	const timerCountUpRef = ref({})
	const startExam = async () => {
		let result = await proxy.Request({
			url: proxy.Api.startExam,
			params: {
				examId: examId.value,
			},
		});
		if (!result) {
			return;
		}
		startExamRef.value.close();
		timerCountUpRef.value.start()
	};

	//选择题目
	const currentExamQuestion = ref({});
	const currentIndex = ref(0);
	const questionChange = (event) => {
		const {
			current,
			source
		} = event.detail;
		currentIndex.value = current;
		currentExamQuestion.value = formData.value.questionList[current];
	};

	//提交考试
	const formData = ref({
		questionList: [],
		answerList: new Map()
	});
	const submit = async () => {
		const questionItemList = formData.value.questionList;
		const hashKey = formData.value.answerList
		// if (hashKey.size < questionItemList.length) {
		// 	for (let i = 0; i < questionItemList.length; i++) {
		// 		const item = questionItemList[i];
		// 		if (!hashKey.has(item.questionId)) {
		// 			currentIndex.value = i;
		// 			break;
		// 		}
		// 	}
		// 	return;
		// }
		const params = {}
		params.examResult = Object.fromEntries(hashKey);
		params.examId = examId.value
		let result = await proxy.Request({
			url: proxy.Api.postExam,
			params: params,
			dataType: "json",
		});
		if (!result) {
			return;
		}
		uni.setStorageSync("answerCache", params.examResult)
		uni.setStorageSync("examInfo", result.data)
		examInfo.value = result.data
		timerCountUpRef.value.stop()
		currentIndex.value = 0;
		currentExamQuestion.value = formData.value.questionList[0];
	};

	const currentQuestion = computed(() => {
		return formData.value.questionList[currentIndex.value] || {};
	});

	//显示更多
	const questionPopupRef = ref();
	const showQuestionList = () => {
		questionPopupRef.value.show();
	};

	const popItemWidth = computed(() => {
		const {
			screenWidth
		} = appInfoStore.getInfo();
		return screenWidth / 6;
	});

	const selectQuestion = (index) => {
		currentIndex.value = index;
		questionPopupRef.value.close();
	};

	const updateCollectHandler = (haveCollect) => {
		currentExamQuestion.value.haveCollect = haveCollect;
	};

	const back = () => {
		uni.navigateBack();
	};
</script>

<style lang="scss" scoped>
	.timer {
		text-align: center;
		width: 100%;
		display: flex;
		justify-content: center;
		align-items: center;
		font-size: 16px;

		.title {
			margin-right: 5px;
		}
	}

	.question-total {
		text-align: center;

		.count {
			color: #7500fb;
			font-weight: bolder;
			font-size: 30px;
		}
	}

	.footer {
		display: flex;
		align-items: center;

		.btn-panel {
			flex: 1;
			color: #fff;
			background: #8f60df;
			text-align: center;
			border-radius: 5px;
			line-height: 40px;
			width: 120px;
			margin: 0px 10px;
		}

		.iconfont {
			color: #848484;

			&::before {
				margin-right: 3px;
				font-size: 20px;
			}
		}

		.icon-collect {
			width: 20px;
		}

		.collected {
			color: #fb2e2e;
		}

		.icon-ok {
			color: #07b107;
			width: 50px;
		}

		.icon-wrong {
			color: #fb2e2e;
			width: 50px;
		}

		.icon-more {
			color: #8f60df;
			width: 70px;
		}
	}

	.pop-question-list {
		max-height: calc(100vh - 200px);
		display: flex;
		flex-wrap: wrap;

		.question-item {
			padding: 10px;

			.item-inner {
				display: flex;
				justify-content: center;
				align-items: center;
				border: 1px solid #ddd;
			}

			.active {
				color: #fff;
				background: #2caff6;
			}

			.answered {
				border: 1px solid #2caff6;
			}
		}
	}
</style>